#include "ImageHistogram.h"
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;

ImageHistogram::ImageHistogram(void)
{
	redBuffer = new PixelBuffer(HIST_WIDTH + 1, HIST_HEIGHT + 1);
	greenBuffer = new PixelBuffer(HIST_WIDTH + 1, HIST_HEIGHT + 1);
	blueBuffer = new PixelBuffer(HIST_WIDTH + 1, HIST_HEIGHT + 1);
	grayBuffer = new PixelBuffer(HIST_WIDTH + 1, HIST_HEIGHT + 1);
	Clear();
}

ImageHistogram::~ImageHistogram(void)
{
	delete redBuffer;
	delete greenBuffer;
	delete blueBuffer;
	delete grayBuffer;
}

void ImageHistogram::Clear()
{
	maxRedCount = maxGreenCount = maxBlueCount = maxGrayCount = 0;
	MaxRedValue = MaxGreenValue = MaxBlueValue = MaxGrayValue = 0;
	MinRedValue = MinGreenValue = MinBlueValue = MinGrayValue = 255;
    for(int i = 0 ; i <= 255 ; i++)
	{
		redCount[i] = 0; greenCount[i] = 0; blueCount[i] = 0; grayCount[i] = 0;
	}
	
    for(int i = 0 ; i < HIST_HEIGHT ; i++)
    {
        for(int j = 0 ; j < HIST_WIDTH ; j++)
        {
			redBuffer->Pixels()[i][j] = Pixel(0, 0, 0);
			greenBuffer->Pixels()[i][j] = Pixel(0, 0, 0);
			blueBuffer->Pixels()[i][j] = Pixel(0, 0, 0);
			grayBuffer->Pixels()[i][j] = Pixel(0, 0, 0);
        }
    }
}

PixelBuffer* ImageHistogram::GrayBuffer()
{
	int rowIndex;
	for(int i = 0 ; i < 256 ; i++)
	{
		rowIndex = HIST_HEIGHT - 1;
		for(int j = 0 ; j < grayCount[i] ; j++)
		{
			grayBuffer->Pixels()[rowIndex--][i] = Pixel(255, 255, 255);
		}
	}
	return this->grayBuffer;
}

PixelBuffer* ImageHistogram::RedBuffer()
{
	int rowIndex;
	for(int i = 0 ; i < 256 ; i++)
	{
		rowIndex = HIST_HEIGHT - 1;
		for(int j = 0 ; j < redCount[i] ; j++)
		{
			redBuffer->Pixels()[rowIndex--][i] = Pixel(255, 0, 0);
		}
	}
	return this->redBuffer;
}

PixelBuffer* ImageHistogram::GreenBuffer()
{
	int rowIndex;
	for(int i = 0 ; i < 256 ; i++)
	{
		rowIndex = HIST_HEIGHT - 1;
		for(int j = 0 ; j < greenCount[i] ; j++)
		{
			greenBuffer->Pixels()[rowIndex--][i] = Pixel(0, 255, 0);
		}
	}
	return greenBuffer;
}

PixelBuffer* ImageHistogram::BlueBuffer()
{
	int rowIndex;
	for(int i = 0 ; i < 256 ; i++)
	{
		rowIndex = HIST_HEIGHT - 1;
		for(int j = 0 ; j < blueCount[i] ; j++)
		{
			blueBuffer->Pixels()[rowIndex--][i] = Pixel(0, 0, 255);
		}
	}
	return blueBuffer;
}

void ImageHistogram::AddPixel(Pixel pixel)
{
	int redComp = pixel.R;
	int greenComp = pixel.G;
	int blueComp = pixel.B;
	int gray = (redComp + greenComp + blueComp) / 3;
	grayCount[gray]++;
	redCount[redComp]++;
	greenCount[greenComp]++;
	blueCount[blueComp]++;

	maxRedCount = redCount[redComp] > maxRedCount ? redCount[redComp] : maxRedCount;
	maxGreenCount = greenCount[greenComp] > maxGreenCount ? greenCount[greenComp] : maxGreenCount;
	maxBlueCount = blueCount[blueComp] > maxBlueCount ? blueCount[blueComp] : maxBlueCount;
	maxGrayCount = grayCount[gray] > maxGrayCount ? grayCount[gray] : maxGrayCount;

	MaxRedValue = redComp > MaxRedValue ? redComp : MaxRedValue;
	MaxGreenValue = greenComp > MaxGreenValue ? greenComp : MaxGreenValue;
	MaxBlueValue = blueComp > MaxBlueValue ? blueComp : MaxBlueValue;
	MaxGrayValue = gray > MaxGrayValue ? gray : MaxGrayValue;

	MinRedValue = redComp < MinRedValue ? redComp : MinRedValue;
	MinGreenValue = greenComp < MinGreenValue ? greenComp : MinGreenValue;
	MinBlueValue = blueComp < MinBlueValue ? blueComp : MinBlueValue;
	MinGrayValue = gray < MinGrayValue ? gray : MinGrayValue;
}

void ImageHistogram::Normalize(int wXh)
{
	for(int i = 0 ; i < 256 ; i++)
	{
		normalizedHistogram[i] = (double)grayCount[i] / (double)(wXh);
		redCount[i]	= (int)((double)redCount[i] / (double)maxRedCount * (double)HIST_HEIGHT);
		greenCount[i] = (int)((double)greenCount[i] / (double)maxGreenCount * (double)HIST_HEIGHT);
		blueCount[i] = (int)((double)blueCount[i] / (double)maxBlueCount * (double)HIST_HEIGHT);
		grayCount[i] = (int)((double)grayCount[i] / (double)maxGrayCount * (double)HIST_HEIGHT);
	}
	int x = 0;
}

int* ImageHistogram::RedHist()
{
	return redCount;
}

int* ImageHistogram::GreenHist()
{
	return greenCount;
}

int* ImageHistogram::BlueHist()
{
	return blueCount;
}

int* ImageHistogram::GrayHist()
{
	return grayCount;
}

double* ImageHistogram::NormalizedHistogram()
{
	return normalizedHistogram;
}